﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DcsGauges.Input.Events;
using System.Diagnostics;
using DcsGauges.Gui.Rendering.Interfaces;

namespace DcsGauges.Input.Processors
{
    class ClickInputProcessor : IInputProcessor
    {
        private uint                        MAX_DELTA_TILL_CLICK            = 5; //allowed to move mouse 5 pixels between mouse down and up till a click won't be a click anymore

        private MouseEvent                  lastDownEvent                   = null;
        private IGuiRenderable              control                         = null;
        private MouseEvent.MouseButtons     clickButton                     = MouseEvent.MouseButtons.None;

        public ClickInputProcessor(IGuiRenderable control, MouseEvent.MouseButtons clickButton)
        {
            if(control == null) throw new ArgumentNullException("control");
            this.control        = control;
            this.clickButton    = clickButton;
        }

        private bool IsInWaitState
        {
            get { return this.lastDownEvent != null; }
        }

        public void InjectMouseEvent(Events.MouseEvent evt, Microsoft.Xna.Framework.GameTime gt)
        {
            if(evt.Button != this.clickButton) return;

            if(this.IsInWaitState == false && evt.EventType == MouseEvent.EventTypes.MouseDown && evt.Button == this.clickButton && control.ViewportRect.Contains(evt.ScreenCoordinates))
            {
                this.EnterWaitState(evt);
            }
            else if(this.IsInWaitState == true && evt.EventType == MouseEvent.EventTypes.MouseUp && evt.Button == this.clickButton && control.ViewportRect.Contains(evt.ScreenCoordinates))
            {
                this.CheckForClick(evt);
            }
            else
            {
                this.ResetState();
            }
        }

        private void EnterWaitState(MouseEvent evt)
        {
            this.lastDownEvent = evt;
        }

        private void CheckForClick(MouseEvent evt)
        {
            Debug.Assert(this.lastDownEvent != null);

            if(MathEx.CompareDelta(evt.ScreenCoordinates.X, this.lastDownEvent.ScreenCoordinates.X, MAX_DELTA_TILL_CLICK) == true && 
                MathEx.CompareDelta(evt.ScreenCoordinates.Y, this.lastDownEvent.ScreenCoordinates.Y, MAX_DELTA_TILL_CLICK) == true)
            {
                this.FireClick();
            }

            this.ResetState();
        }

        private void ResetState()
        {
            this.lastDownEvent = null;
        }

        private void FireClick()
        {
            if (this.Click != null)
            {
                this.Click(this, new EventArgs());
            }
        }

        public event EventHandler<EventArgs> Click;
    }
}
